
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>

class ThreadPool {
public:
    ThreadPool(size_t numThreads);
    ~ThreadPool();

    // 添加任务到线程池
    void enqueueTask(std::function<void()> task);

private:
    // 工作线程函数
    void worker();

    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;

    std::mutex queueMutex;
    std::condition_variable condition;
    std::atomic<bool> stop;
};

/*
workers（线程池中的工作线程）：是 std::vector<std::thread>，保存了线程池中的所有工作线程。这些线程是由 主线程创建，但是每个线程在执行时都会使用其他线程池中的共享资源。线程对象本身是由主线程创建和管理的，但它们会共同访问 共享任务队列 和 共享条件变量。

tasks（任务队列）：是 std::queue<std::function<void()>>，这是一个保存任务的队列。所有线程都会访问这个队列，因此是 共享的。任务队列由所有工作线程共同消费，每个线程从队列中获取任务并执行。

queueMutex（队列的互斥锁）：是 std::mutex，用于同步访问任务队列 tasks。因为多个线程会并发地访问 tasks 队列，所以需要通过 queueMutex 来保护任务队列，防止出现竞态条件。queueMutex 是 共享的，所有线程都需要获取这个锁来对任务队列进行操作。

condition（条件变量）：是 std::condition_variable，用于同步任务队列中的任务和线程的等待。当任务队列中有新任务时，工作线程会被通知继续工作。条件变量本身是 共享的，所有线程都会使用它来进行等待或通知。

stop（停止标志）：是 std::atomic<bool>，用于控制线程池是否停止运行。当设置为 true 时，所有线程会停止工作并退出。stop 是 共享的，所有线程都会检查它的状态，以决定是否继续运行。


启动线程:
emplace_back 方法会创建一个新的 std::thread 对象，并立即启动它。
每个线程执行 worker() 函数，这个函数是线程的主循环，负责从任务队列中提取任务并执行。

创建一个新的线程，并在该线程中执行 worker() 函数。
通过 [this] 捕获当前 ThreadPool 对象的上下文，使得 worker() 函数可以访问 ThreadPool 类的成员变量和其他成员函数

线程的生命周期:
线程在 ThreadPool 对象的构造过程中被启动，并在 ThreadPool 对象的生命周期内持续运行，直到 ThreadPool 的析构函数被调用。
在析构函数中，所有线程会被通知停止，并通过 join() 等待它们完成。

细节：
(1) emplace_back 直接在向量的内存中构造对象
(2) 当你创建一个 std::thread 对象时，构造函数会接受一个可调用对象（如函数指针、lambda 表达式、成员函数等）作为参数，并立即启动一个新线程来执行这个可调用对象。
*/

ThreadPool::ThreadPool(size_t numThreads) : stop(false) {
    for (size_t i = 0; i < numThreads; ++i) {
        workers.emplace_back([this] { worker(); });
    }
}

ThreadPool::~ThreadPool() {
    stop = true;
    condition.notify_all();
    for (std::thread &worker : workers) {
        if (worker.joinable()) {
            worker.join();
        }
    }
}

void ThreadPool::enqueueTask(std::function<void()> task) {
    {
        std::unique_lock<std::mutex> lock(queueMutex);
        tasks.emplace(std::move(task));
    }
    condition.notify_one();
}

void ThreadPool::worker() {
    while (!stop) {
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            condition.wait(lock, [this] { return stop || !tasks.empty(); });
            if (stop && tasks.empty()) {
                return;
            }
            task = std::move(tasks.front());
            tasks.pop();
        }
        task();
    }
}

int main() {
    ThreadPool pool(4); //主线程创建

    for (int i = 0; i < 8; ++i) {
        pool.enqueueTask([i] {
            std::cout << "Task " << i << " is executing.\n";
        });
    }

    std::this_thread::sleep_for(std::chrono::seconds(1)); // 等待任务完成
    return 0;
}
